#ifndef BOT_H_
#define BOT_H_

#include "State.h"
#include "fieldgenerator.h"

#include <map>
#include <vector>
#include <utility>
#include <deque>

class PathQueueEntry {
public:
    Location antLoc;
    std::stack<int> path;
public:
    PathQueueEntry(const Location& loc,
		   const std::stack<int>& antpath):antLoc(loc),path(antpath) {}
    bool operator < (const PathQueueEntry& other) const{
	return path.size() > other.path.size();
    }
};

typedef std::priority_queue<PathQueueEntry> PathQueue;

/*
    This struct represents your bot in the game of Ants
*/

enum BATTLEMETHOD {
    DMG_BASED=0,
    FOCUS_BASED
};

class Bot
{
private:
    State state;
    PotentialField field;
    std::map< int , std::vector<Location> > squadList;
    std::map< Location,bool > inSquad;
    std::map< Location,bool > processedAnts;
    std::vector<Location> explorers;
public:
    Bot();

    void playGame();    //plays a single game of Ants

    void makeMoves();   //makes moves for a single turn
    void endTurn();     //indicates to the engine that it has made its moves    
private:

    int  resolveBattleSimple(const Location& nLoc,BATTLEMETHOD battleMethod) ;
    int  resolveBattleDmgBased(const Location& nLoc);
    int  resolveBattleFocusBased(const Location& nLoc);

    //Squad management  functions
    void buildSquads();
    void moveSquad(const int& squad_id);
    bool isInSquad(const Location& ant) const;
    void clearSquads();
    bool moveSquadTo(const std::vector<Location>::iterator& start,
		     const std::vector<Location>::iterator& end,
		     const Location& loc,int& shortestPathLen);
    void printSquad(const int& squad_id) ;


    bool findNearbyValidLoc(const Location& loc,Location& validLoc);
    //Squad objective functions
    bool squadHuntFood(const int& squad_id);
    bool squadHuntFood2(const int& squad_id);
    bool squadHuntHill(const int& squad_id);
    bool squadHuntAnt(const int& squad_id);
    bool squadDefendHill(const int& squad_id);
    bool squadPotentialBasedMove(const int& squad_id);
    void tryEscape(const Location& loc);
    bool isFoodAdjacent(const Location& loc);
    //returns a list of paths for each ant in squad to loc
    PathQueue generateSquadMoves(std::vector<Location>::iterator start,
				 std::vector<Location>::iterator end,
				 const Location& loc);
    void safeMakeMove(const Location& ant,int direction);

    //pledge algorithm based solving 
    void antSolveMap(const Location& ant);
    void solveMap(const int& squad_id);

    //old per ant history based moving
    void moveToFrontLine(const int& squad_id);

    //vision increased based exploration
    bool moveToFrontLineHistoryBased(const int& squad_id);

    //multi source BFS based exploration
    void antMakeExplorer(const Location& loc);
    void squadMakeExplorers(const int& squad_id);
    void multiSourceBFSExplore();

    bool shouldAttack() const;;
};

#endif //BOT_H_
